#include "xxtea.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static int getHashCode(const char* buffer, unsigned int len) 
{
    int hashCode = 0;
    while ((buffer != NULL) && (len-- > 0)) {
        hashCode = 31 * hashCode + *(buffer++);
    }
    return hashCode;
}

int getDeviceKey(XXTEA_TYPE *key, const char * devicekey,unsigned int len)
{
    if (!key)
        return -1;

    if (!devicekey)
        return -1;
    
    const unsigned XXTEA_TYPE keylen = 24; //key的值长
    if (len != keylen)
        return -1;

    if (strlen(devicekey) != keylen)
        return -1;

    const char* tmp = devicekey;
    unsigned XXTEA_TYPE i = 0;
    unsigned XXTEA_TYPE j = 0;
    for (i = 0; i < keylen; i= i + 6)
    {
        key[j++] = getHashCode(&tmp[i], 6);
    }
    return 0;
}


#define MX ((z>>5^y<<2) + (y>>3^z<<4) ^ (sum^y) + (k[p&3^e]^z))
/*
*
*v 是一个n个字的数组
*key 是4个字节的密钥
*n 数组中字的个数，正为加密，负为解密
*
*/
XXTEA_TYPE btea(XXTEA_TYPE* v, XXTEA_TYPE n, XXTEA_TYPE* k)
{
    unsigned XXTEA_TYPE z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9;
    int p, q ;
    if (n > 1) {          /* Coding Part */
        q = 6 + 52/n;
        while (q-- > 0)
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p=0; p<n-1; p++) y = v[p+1], z = v[p] += MX;
            y = v[0];
            z = v[n-1] += MX;
        }
        return 0 ; 
    } else if (n < -1)
    {  /* Decoding Part */
        n = -n;
        q = 6 + 52/n;
        sum = q*DELTA ;
        while (sum != 0) 
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX;
            z = v[n-1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
    return 0;
    }
    return 1;
}


int XXTEAGetBufferLength(int srcLength, bool isEncode)
{
    if (isEncode)
    {
        return ((srcLength + 3)/4 +1) * sizeof(XXTEA_TYPE);
    }
    else
    {
        return ((srcLength/sizeof(XXTEA_TYPE)) - 1) * sizeof(XXTEA_TYPE);
    }
    
}

bool XXTEAEncode(char* lpDstBuffer, const char* lpSrcBuffer, int nLength, XXTEA_TYPE* lpKey)
{
    XXTEA_TYPE v_len = XXTEAGetBufferLength(nLength, true);
    memset (lpDstBuffer, 0 ,v_len);
    memcpy(lpDstBuffer, lpSrcBuffer, nLength);
    
    int tmp = ((nLength + 3)/sizeof(XXTEA_TYPE)) * sizeof(XXTEA_TYPE);
    memcpy(lpDstBuffer + tmp, (void*)&nLength, sizeof(int));
    
    XXTEA_TYPE n = v_len/sizeof(XXTEA_TYPE);
    XXTEA_TYPE ret = btea((XXTEA_TYPE *) lpDstBuffer, n, lpKey);
    return(ret == 0) ? true : false;
}

XXTEA_TYPE XXTEADecode(char* lpDstBuffer, const char* lpSrcBuffer, int nLength, XXTEA_TYPE* lpKey)
{
    XXTEA_TYPE n = nLength/sizeof(XXTEA_TYPE);
    btea((XXTEA_TYPE *) lpSrcBuffer, -n, lpKey);
    //XXTEA_TYPE v_len = XXTEAGetBufferLength(nLength, false);
    XXTEA_TYPE *tmp = (XXTEA_TYPE*)lpSrcBuffer;
    XXTEA_TYPE len = tmp[n-1];
    
    memset(lpDstBuffer, 0, len);
    memcpy(lpDstBuffer, lpSrcBuffer, len);
    //printf("----len:%ld\n",len);
    return len;
}

